浅谈 C++ 不定参数

你是否遇到过一个函数要传的参数不确定的问题?你是否想要写一个方便的函数可以处理任意多个数的最小值(最大值、加和),而不是套很多层的 min(max、+)?C++ 函数不定参数可以实现这些。

先来说说多个数最小值的函数。

我们首先声明一个函数:

int Min(int tot, ...);

这里 tot 表示要求最小值的数的个数,后面的 ... 是数的列表。

我们需要调用后面的列表,在函数中定义 va_list,长度为 tot:

int Min(int tot, ...) {
    va_list a;
    va_start(a, tot);
    // Do something..
}

然后开始写比较,每次从列表中取一个 int 元素,与当前最小值比较(这里最小值设置为 0x3f3f3f3f),取元素时使用 va_arg(),最后结束列表即可。

int Min(int tot, ...) {
	va_list a;
	va_start(a, tot);
	int res = 0x3f3f3f3f;
	for(int i=1;i<=tot;i++) {
		res = min(res, va_arg(a, int));
	}
	va_end(a);
	return res;
}

我们试着调用 Min(4, -1, 3, 2, 0),发现返回值为 -1,即 -1, 3, 2, 0 这四个数中的最小值。


以上是 C++98 支持的最基本的不定参数用法,下面讲解一个 C++11 新增的技巧——可变参数模板。

C++11 允许我们这样定义一个可变参数类模板:

template<typename ... Types>
class QAQ {
    // Do something..
};

这样我们就可以用任意数量的变量类型来初始化 QAQ:

QAQ<> c1;
QAQ<int> c2;
QAQ<int, char> c3;

如果想要避免出现使用 0 个模板参数来初始化的情况,我们可以这么写:

template<typename T, typename ... Types>
class QAQ2 {
    // Do something..
};

可变参数函数模板如下(这里是一个输出不同类型的变量的函数):

void print() { // 这个函数啥都不用做,只是为了防止递归到最后一层后出现的函数未定义的现象,可以自行探索
    ;
}
template<typename T, typename ... Types>
void print(T arg, Types ... args) {
    cout<<arg<<endl;
    print(args ...);
}

这样我们就可以输出一串任意长度、任意类型的列表了:

#include <bits/stdc++.h>
using namespace std;

void print() {
    ;
}
template<typename T, typename ... Types>
void print(T arg, Types ... args) {
    cout<<arg<<endl;
    print(args ...);
}

int main() {
    int a = 0;
    print(1, 2, 0.18, "QAQ", a, &a);
    return 0;
}

输出结果:

1
2
0.18
QAQ
0
0x73fe1c

(注:最后一个输出的是变量 a 的地址,可能因人而异)

以上就是不定参数的基本用法,大家学会了吗?可以自己写写试试哟~